
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "keybutton.h"
#include "led.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static u8 gKeyScan = 0;
static u8 gKeyNew = KEYBUTTON_NONE;
static u8 gKeyOld = KEYBUTTON_NONE;
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/


void KeyButton_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	EXTI_InitTypeDef EXTI_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;


	/* GPIOC Periph clock enable */
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);

	/* Configure PC[3:0] in output pushpull mode */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_Init(GPIOC, &GPIO_InitStructure);

	GPIO_Write(GPIOC, (GPIO_ReadOutputData(GPIOC) | (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3)));


	/* Enable GPIO clock */
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD, ENABLE);

	/* Configure PD[15:10] pin in input pull-up mode */
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
	GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15);
	GPIO_Init(GPIOD, &GPIO_InitStructure);


	/* Enable SYSCFG clock */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

	/* Connect EXTI[15:10] Line to PD[15:10] pin */
	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOD, EXTI_PinSource10);
	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOD, EXTI_PinSource11);
	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOD, EXTI_PinSource12);
	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOD, EXTI_PinSource13);
	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOD, EXTI_PinSource14);
	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOD, EXTI_PinSource15);

	/* Configure EXTI[15:10] line */
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_InitStructure.EXTI_Line = EXTI_Line10;
	EXTI_Init(&EXTI_InitStructure);
	EXTI_InitStructure.EXTI_Line = EXTI_Line11;
	EXTI_Init(&EXTI_InitStructure);
	EXTI_InitStructure.EXTI_Line = EXTI_Line12;
	EXTI_Init(&EXTI_InitStructure);
	EXTI_InitStructure.EXTI_Line = EXTI_Line13;
	EXTI_Init(&EXTI_InitStructure);
	EXTI_InitStructure.EXTI_Line = EXTI_Line14;
	EXTI_Init(&EXTI_InitStructure);
	EXTI_InitStructure.EXTI_Line = EXTI_Line15;
	EXTI_Init(&EXTI_InitStructure);

	/* Enable and set EXTI15_10 Interrupt to the lowest priority */
	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);


	/* TIM19 clock enable */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM19, ENABLE);

	/* Enable the TIM19 gloabal Interrupt */
	NVIC_InitStructure.NVIC_IRQChannel = TIM19_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

	/* Time base configuration */
	TIM_TimeBaseStructure.TIM_Period = 10000 - 1;	// 10 mSec
	TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1;	// 1MHz
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInit(TIM19, &TIM_TimeBaseStructure);

	/* TIM Interrupts enable */
	TIM_ITConfig(TIM19, TIM_IT_Update, ENABLE);

	/* TIM19 enable counter */
	TIM_Cmd(TIM19, ENABLE);
}

u8 KeyButton_Proc(void)
{
	u8 key = KEYBUTTON_NONE;

	if (KEYBUTTON_NONE != gKeyNew) {
		// GPD[15:10]
		if (0xFC00 == (GPIOD->IDR & 0xFC00)) {
			gKeyOld = gKeyNew = KEYBUTTON_NONE;

			TIM19->CR1 |= TIM_CR1_CEN;	//TIM_Cmd(TIM19, ENABLE);
		} else {
			if (gKeyOld != gKeyNew) {
				key = gKeyOld = gKeyNew;
			}
		}

		/*switch (key) {
		case KEYBUTTON_0:
			printf("KEYBUTTON_0\r\n");
			break;
		case KEYBUTTON_1:
			printf("KEYBUTTON_1\r\n");
			break;
		case KEYBUTTON_2:
			printf("KEYBUTTON_2\r\n");
			break;
		case KEYBUTTON_3:
			printf("KEYBUTTON_3\r\n");
			break;
		case KEYBUTTON_4:
			printf("KEYBUTTON_4\r\n");
			break;
		case KEYBUTTON_5:
			printf("KEYBUTTON_5\r\n");
			break;
		case KEYBUTTON_6:
			printf("KEYBUTTON_6\r\n");
			break;
		case KEYBUTTON_7:
			printf("KEYBUTTON_7\r\n");
			break;
		case KEYBUTTON_8:
			printf("KEYBUTTON_8\r\n");
			break;
		case KEYBUTTON_9:
			printf("KEYBUTTON_9\r\n");
			break;
		case KEYBUTTON_DOT:
			printf("KEYBUTTON_DOT\r\n");
			break;
		case KEYBUTTON_BS:
			printf("KEYBUTTON_BS\r\n");
			break;
		case KEYBUTTON_UP:
			printf("KEYBUTTON_UP\r\n");
			break;
		case KEYBUTTON_DOWN:
			printf("KEYBUTTON_DOWN\r\n");
			break;
		case KEYBUTTON_LEFT:
			printf("KEYBUTTON_LEFT\r\n");
			break;
		case KEYBUTTON_RIGHT:
			printf("KEYBUTTON_RIGHT\r\n");
			break;
		case KEYBUTTON_F1:
			printf("KEYBUTTON_F1\r\n");
			break;
		case KEYBUTTON_F2:
			printf("KEYBUTTON_F2\r\n");
			break;
		case KEYBUTTON_F3:
			printf("KEYBUTTON_F3\r\n");
			break;
		case KEYBUTTON_OK:
			printf("KEYBUTTON_OK\r\n");
			break;
		}*/
	}

	return key;
}

void EXTI15_10_IRQHandler(void)
{
	TIM19->CR1 &= ~TIM_CR1_CEN;	//TIM_Cmd(TIM19, DISABLE);

	for (u32 i=0; i<6; i++) {
		u32 EXTI_Line = (EXTI_Line10 << i);

		//if (SET == EXTI_GetITStatus(EXTI_Line)) {
		//	EXTI_ClearITPendingBit(EXTI_Line);
		if ((EXTI->IMR & EXTI_Line) && (EXTI->PR & EXTI_Line)) {
			EXTI->PR = EXTI_Line;

			u16 status = (GPIOD->IDR & (GPIO_Pin_10 << i));	//GPIO_ReadInputDataBit(GPIOD, (GPIO_Pin_10 << i));
			//printf("EXTI_Line%d %s !!!\r\n", (10+i), status ? "released" : "pressed");

			if (KEYBUTTON_NONE == gKeyNew) {
				if (0 == status) {
					if (EXTI_Line10 == EXTI_Line) {
						gKeyNew = KEYBUTTON_OK;
					} else {
						gKeyNew = i*4 + gKeyScan;
					}
				}
			}
			break;
		}
	}

	//TIM19->CR1 |= TIM_CR1_CEN;	//TIM_Cmd(TIM19, ENABLE);
}

void TIM19_IRQHandler(void)
{
	//if (TIM_GetITStatus(TIM19, TIM_IT_Update) != RESET) {
	//	TIM_ClearITPendingBit(TIM19, TIM_IT_Update);
	if ((TIM19->SR & TIM_IT_Update) && (TIM19->DIER & TIM_IT_Update)) {
		TIM19->SR = (u16)~TIM_IT_Update;

		u16 gpio = (u16)GPIOC->ODR | 0x0F;
		GPIOC->ODR = gpio & ~(GPIO_Pin_0 << gKeyScan);

		gKeyScan++;
		gKeyScan = gKeyScan % 4;
	}
}
